// threadserver.cpp : Defines the entry point for the console application.
//

#include <iostream>
#include <Sock.h>

#include <KeyParser.h>
#include <map.h>
#include <BuffQue.h>

#include <MakeID.h>


#include <Client.h>

int ucp()
{

	CSock	ServerSock;
	CSock	PeerSock;
	
	ServerSock.Init( CSock::UDP );
	
	ServerSock.SetReuseAddr( true );
	ServerSock.SetLinger( true, 60 );

	ServerSock.Bind( 12311 );
		
	char szPacket[CSock::MAXBUFF];
	size_t nPacketSize = CSock::MAXBUFF ;
	memset( szPacket, 0, CSock::MAXBUFF );
	
	int nRecvSize = 0;
	int nSendSize = 0;
	std::cout << "[ " << ServerSock.GetSock() << "] " << "ready " << std::endl;	
	
	do
	{		
		nRecvSize = ServerSock.Recv_udp( PeerSock, szPacket, nPacketSize );
		std::cout << "[" << PeerSock.GetSock() <<"] recv ( " << nRecvSize << " ): " << szPacket << std::endl;

		if( nRecvSize )
		{
			nSendSize = ServerSock.Send_udp( PeerSock, szPacket, nPacketSize );
			std::cout << "[" << PeerSock.GetSock() <<"] send ( " << nSendSize << " ): " << szPacket << std::endl;
			
		}
		
		memset( szPacket, 0, CSock::MAXBUFF );
		nPacketSize = 0;

	} while( 0 < nRecvSize );
	
	
	PeerSock.Close();	
	ServerSock.Close();

	return 0;

}



int tcp()
{
	
	CSock ServerSock;
	
	ServerSock.Init();	

	ServerSock.SetReuseAddr( true );
	ServerSock.SetLinger( true, 60 );

	ServerSock.Bind( 12311 );
	ServerSock.Listen();
	
	char szPacket[CSock::MAXBUFF];
	size_t nPacketSize = 0;
	memset( szPacket, 0, CSock::MAXBUFF );
	
	int nRecvSize = 0;
	int nSendSize = 0;
	std::cout << "[ " << ServerSock.GetSock() << "] " << "ready " << std::endl;	
	
	CClient client;	
	ServerSock.Accept( *client.GetSocket() );
	std::cout << "[" << client.GetSocket()->GetSock() <<"] connect " << std::endl;
	
	do
	{
		nRecvSize = client.Recv( szPacket, nPacketSize );
		std::cout << "[" << client.GetSocket()->GetSock() <<"] recv ( " << nRecvSize << " ): " << szPacket << std::endl;
		
		if( nPacketSize )
		{
			nSendSize = client.Send( szPacket, nPacketSize );
			std::cout << "[" << client.GetSocket()->GetSock() <<"] send ( " << nSendSize << " ): " << szPacket << std::endl;
			
		}
		
		memset( szPacket, 0, CSock::MAXBUFF );
		nPacketSize = 0;
	} while( 0 < nRecvSize );
	
	
	client.Close();
	
	
	
	ServerSock.Close();
	
	return 0;
}




int tcp_select()
{
/*
	int a[] = { 1,2,3};
	char* sz[]=
	{
		"aaa",
		"bbb",
		"cccccc"
	};

	CMap<int, char*> maps;
	size_t nSize = 0;
	for( size_t i = 0; i < 3; i++)
		nSize = maps.add( a[i], sz[i] );

	maps.resetCursor();
	int nKey = 0;
	while( 0 <= maps.getCursor_key( nKey )  )
	{
		std::cout << " nKey : " << nKey << std::endl;
		maps.nextCursor();
	}
	*/
	

	CSock ServerSock;
	
	ServerSock.Init();	

	ServerSock.SetReuseAddr( true );	
	ServerSock.SetLinger( true, 60 );

	ServerSock.Bind( 12311 );
	ServerSock.Listen();
	
	char szPacket[CSock::MAXBUFF];
	size_t nPacketSize = 0;
	memset( szPacket, 0, CSock::MAXBUFF );
	
	int nRecvSize = 0;
	int nSendSize = 0;
	std::cout << "[ " << ServerSock.GetSock() << "] " << "ready " << std::endl;	

	fd_set	readset, tempset;
	TIMEVAL timeout;

	FD_ZERO( &readset );
	FD_SET( ServerSock.GetSock(), &readset );
	
	

	CMakeID Ids;
	CMap<size_t, CClient*> Users;
	CClient* pClient = 0;
	while(1)
	{
		int fd;
		int i = 0;

		tempset = readset;
		timeout.tv_sec = 5;
		timeout.tv_usec = 0;

		if( 0 > select( FD_SETSIZE, &tempset, 0,0, &timeout ) )
			break;

		for( i = 0; i < FD_SETSIZE; i++ )
		{
			#ifdef WIN32
				fd = readset.fd_array[i];
			#else
				fd = i;
			#endif
			

			if( !FD_ISSET(fd, &tempset) )			
				continue;
			
			if( ServerSock.GetSock() == fd )
			{				
				CSock sockPeer;

				ServerSock.Accept( sockPeer );
				FD_SET( sockPeer.GetSock(), &readset );
				
				pClient = new CClient;
				pClient->SetSocket( sockPeer );
				pClient->SetIdent( Ids.Get() );

				Users.add( pClient->GetIdent(), pClient );

				std::cout << "accpet [ " << pClient->GetSocket()->GetSock() << "]" << " / ident : " << pClient->GetIdent() << std::endl;					 				
				
			}
			else
			{		
				CClient* pClient = 0;
				Users.resetCursor();
				while( 0 <= Users.getCursor_data(pClient) )
				{
					if( pClient->GetSocket()->GetSock() != fd )
					{
						Users.nextCursor();	
						continue;
					}


					nRecvSize = 0;
					nSendSize = 0;
					nPacketSize = 0;
					
					nPacketSize = 0;
					memset( szPacket, 0, CSock::MAXBUFF );	
					
					nRecvSize = pClient->Recv( szPacket, nPacketSize );
					std::cout << "[" << pClient->GetSocket()->GetSock() <<"] recv ( " << nRecvSize << " ): " << szPacket << std::endl;
					if( nPacketSize )
					{
						nSendSize = pClient->Send( szPacket, nPacketSize );
						std::cout << "[" << pClient->GetSocket()->GetSock() <<"] send ( " << nSendSize << " ): " << szPacket << std::endl;
					}
					else
					{
						std::cout << "close [ " << pClient->GetSocket()->GetSock() << "]" << std::endl;	
						
						FD_CLR( fd, &readset );
						pClient->Close();
					}					

					Users.nextCursor();
				}				
			}
		}
	}
	

	Users.resetCursor();
	CClient* pDelClient = 0;
	while( 0 <= Users.getCursor_data( pDelClient )  )
	{
		SAFE_DELETE( pDelClient );
		Users.nextCursor();
	}	

	ServerSock.Close();
	
	return 0;
}


int main(int argc, char* argv[])
{
	
	
#ifdef WIN32
	WSADATA wsaData;
	if( 0 > WSAStartup( MAKEWORD(2,2), &wsaData) )
		return -1;
#endif
	
//	tcp();
//	ucp();

		
	tcp_select();
	


#ifdef WIN32
	WSACleanup();
#endif

	return 0;
}

